package com.nakamachizu.controller.mixi;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.tools.generic.DateTool;
import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.datastore.Datastore;
import org.slim3.util.StringUtil;
import org.slim3.util.TimeZoneLocator;
import org.w3c.dom.Document;

import com.nakamachizu.constant.MixiConstant;
import com.nakamachizu.model.MapData;
import com.nakamachizu.model.mixi.BasePersonFriendModel;
import com.nakamachizu.model.mixi.FriendMapModel;
import com.nakamachizu.model.mixi.PersonFriendsModel;
import com.nakamachizu.model.session.MixiFriendSession;
import com.nakamachizu.service.MapDataService;
import com.nakamachizu.service.XmlGenService;
import com.nakamachizu.service.mixi.RestfulService;
import com.nakamachizu.service.mixi.SessionService;
import com.nakamachizu.service.mixi.ValidatingSignedRequestsService;

public class ListController extends Controller {
    
    private static final Logger log = Logger.getLogger(ListController.class.getName());
    private String ownerId;
    private String viewerId;
    private String appId;
    private String startIndex;
    
    private int total = 0;
    private int perPage = 0;

    @Override
    public Navigation run() throws Exception {

        ValidatingSignedRequestsService vsrf = new ValidatingSignedRequestsService();
        Map<String,String> reqMap = vsrf.verifyFetch(request);
        
        ownerId = requestScope(ValidatingSignedRequestsService.OPENSOSIAL_OWNER_ID);
        viewerId = requestScope(ValidatingSignedRequestsService.OPENSOSIAL_VIEWER_ID);
        appId = requestScope(ValidatingSignedRequestsService.OPENSOSIAL_APP_ID);
        startIndex = reqMap.get("startIndex");
        
        if(StringUtil.isEmpty(startIndex)){
            startIndex = Integer.toString(RestfulService.DEFAULT_START_INDEX);
        }
        
        List<FriendMapModel> mapList = null;
        
        SessionService ss = new SessionService();
        MixiFriendSession mfs = ss.getMixiFriendSession(viewerId);
        
        if(mfs != null){
            mapList = mfs.getFriendMapModelListRef().getModelList();
            
        }else{
            mapList = new ArrayList<FriendMapModel>();
            
            RestfulService rfs = new RestfulService();
            rfs.makeSignature(viewerId, RestfulService.TARGET_UID_ME, RestfulService.TARGET_TYPE_FRIENDS, RestfulService.FORMAT_JSON, RestfulService.DEFAULT_COUNT, Integer.parseInt(startIndex));
    
            
            if(rfs.request() == 200){
                PersonFriendsModel friends = rfs.getPersonFriendsModel();
                if(friends != null && friends.getTotalResults() > 0){
                    
                    MapDataService mds = new MapDataService();
                    for(Map<String,String>entry : friends.getEntry()){
                        FriendMapModel model = new FriendMapModel();
                        model.setMixiId(entry.get(BasePersonFriendModel.ID));
                        model.setDisplayName(entry.get(BasePersonFriendModel.DISPLAY_NAME));
                        
                        MapData data = mds.getMapData(model.getMixiId() + MixiConstant.MIXI_MAIL_ADDRESS());
                        if(data != null){
                            model.setAccessKey(data.getAccessKey());
                            model.setAccessLevel(data.getAccessLevel());
                            model.setTitle(data.getTitle());
                            model.setExpire(data.getExpire());
                            model.setPeople(data.getMemberDataListRef().getModelList().size());
                            mapList.add(model);
                        }
                    }
                    
                    Calendar now = Calendar.getInstance(TimeZoneLocator.get());
                    now.add(Calendar.MINUTE, MixiConstant.MIXI_SESSION_MINUTES());
                    mfs = new MixiFriendSession();
                    mfs.setMixiId(viewerId);
                    mfs.setExpireDate(now.getTime());
                    for(FriendMapModel model : mapList){
                        model.getMixiFriendSessionRef().setModel(mfs);
                        Datastore.put(model);
                    }                    
                    Datastore.put(mfs);
                }
            }else if(rfs.request() == 401){
                //log.info(rfs.getContents());
                // 401 Authorization Required
                // アプリ起動してないとか、何かが原因で取得失敗
                // 空のmixi friend session生成 5分間は空のセッション
                Calendar now = Calendar.getInstance(TimeZoneLocator.get());
                now.add(Calendar.MINUTE, 5);
                mfs = new MixiFriendSession();
                mfs.setMixiId(viewerId);
                mfs.setExpireDate(now.getTime());
                Datastore.put(mfs);
            }
        }

        MapDataService mds = new MapDataService();
        MapData myMap = mds.getMapData(viewerId + MixiConstant.MIXI_MAIL_ADDRESS());
        
        XmlGenService xgs = new XmlGenService();
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setValidating(false);
        DocumentBuilder builder = factory.newDocumentBuilder();

        
        Document xml = null;
        
        Velocity.init("WEB-INF/velocity_conf.properties");
        VelocityContext context = new VelocityContext();

        if(mapList != null){
            total = mapList.size();
        }
        
        context.put("appid", appId);
        context.put("viewerid", viewerId);
        context.put("ownerid", ownerId);
        context.put("mymap", myMap);
        if(myMap != null){
            context.put("myMapPeople", myMap.getMemberDataListRef().getModelList().size());
        }else{
            context.put("myMapPeople", 0);
        }
        context.put("total", total);
        context.put("perpage", RestfulService.DEFAULT_COUNT);
        context.put("page", startIndex);

        context.put("date", new DateTool());
        context.put("mapList", mapList);
        
        String xmlStr = null;
        StringWriter sw = new StringWriter();
        Template template = Velocity.getTemplate("mixi/pc/list.xml", "UTF-8");
        template.merge(context, sw);
        xmlStr = sw.toString();
        sw.flush();
        
        //log.info(xmlStr);
        
        InputStream is = new ByteArrayInputStream(xmlStr.getBytes("UTF-8"));
        try{
            xml = builder.parse(is);
        }finally{
            is.close();
        }
        
        xgs.printXml(response.getOutputStream(), xml);
        
        return null;
    }
}
